package com.wit.witmg.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wit.witmg.constants.SysConstants;
import com.wit.witmg.entity.TUser;
import com.wit.witmg.mapper.TUserMapper;
import com.wit.witmg.service.ITUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wit.witmg.util.*;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author bob
 * @since 2025-02-24
 */
@Service
@RequiredArgsConstructor
public class TUserServiceImpl extends ServiceImpl<TUserMapper, TUser> implements ITUserService {
    final RedisUtil redisUtil;

    @Override
    public Object login(HttpServletRequest request, String code) {
        return getLogin(code);
    }

    @Override
    public Object bindPhone(HttpServletRequest request, String code) {
        String openid = StringUtils.instance.getMyOpenid(request);
        String wxPhone = getWxPhone(request, code);
        QueryWrapper<TUser> qw = new QueryWrapper<>();
        qw.eq("openid",openid);
        TUser t=new TUser();
        t.setPhone(Long.parseLong(wxPhone));
        if( update(t,qw)){
            cleanRedis(openid);
            return JsonResult.success(t.getPhone());
        }
        return JsonResult.success(ErrorCode.ERR_504);
    }

    @Override
    public Object loginApp(HttpServletRequest request, String code) {
        String wxLoginUrl="https://api.weixin.qq.com/sns/oauth2/access_token";
        Map<String, Object> map = new HashMap<>();
        map.put("appid",SysConstants.APPID_APP);
        map.put("secret",SysConstants.SECRET_APP);
        map.put("code",code);
        map.put("grant_type","authorization_code");
        String loginRes = HttpUtils.instance.doGet(wxLoginUrl,map);
        redisUtil.set("wxlogapp",loginRes);
        // 解析返回信息
        JSONObject loginObj = JSON.parseObject(loginRes);
        if(loginObj==null ){
            return JsonResult.error(ErrorCode.ERR_601);
        }
        if(loginObj.containsKey("errcode")){
            return JsonResult.error(loginObj);
        }
        // 用户唯一标识
        String unionid;
        if(loginObj.containsKey("unionid")){
            unionid = loginObj.getString("unionid");
        }else{
            return JsonResult.error(ErrorCode.ERR_601);
        }

        JSONObject obj= StringUtils.instance.getBaseResultObj();
        obj.put("unionid",unionid);
        obj.put("base",getEntity(unionid));
        return obj;
    }

    @Override
    public Object add(HttpServletRequest request, String json) {
        TUser t= JSON.parseObject(json,TUser.class);
        if(t.getId()>0){
            boolean bl= updateById(t);
            if(bl){
                return JsonResult.success(t);
            }
        }
        return JsonResult.error(ErrorCode.ERR_200);
    }

    public String getAccessToken() {
        if(redisUtil.hasKey(RedisKeys.accessToken.getVal())  && redisUtil.get(RedisKeys.accessToken.getVal())!=null) {
            return redisUtil.get(RedisKeys.accessToken.getVal()).toString();
        }
        String accentTokenUrl = "https://api.weixin.qq.com/cgi-bin/token";
        Map<String, Object> map=new HashMap<>();
        map.put("grant_type","client_credential");
        map.put("appid",SysConstants.APPID);
        map.put("secret",SysConstants.SECRET);

        //发送请求
        String result = HttpUtils.instance.doGet(accentTokenUrl,map);
        JSONObject jsonObject = JSON.parseObject(result);
        String accessToken= jsonObject.getString("access_token");
        redisUtil.set(RedisKeys.accessToken.getVal(),accessToken,7000);
        return accessToken;
    }

    private Object getLogin(String code){
        String wxLoginUrl="https://api.weixin.qq.com/sns/jscode2session?";
        Map<String, Object> map = new HashMap<>();
        map.put("appid", SysConstants.APPID);
        map.put("secret",SysConstants.SECRET);
        map.put("js_code",code);
        map.put("grant_type","authorization_code");
        String loginRes = HttpUtils.instance.doGet(wxLoginUrl,map);
        redisUtil.set("wxlog",loginRes);
        // 解析返回信息
        JSONObject loginObj = JSON.parseObject(loginRes);
        if(loginObj==null ){
            return JsonResult.error(ErrorCode.ERR_601);
        }
        if(loginObj.containsKey("errcode")){
            return JsonResult.error(loginObj);
        }
        // 用户唯一标识
        String openid;
        if(loginObj.containsKey("unionid")) {
            openid = loginObj.getString("unionid");
        }else{
            return JsonResult.error(ErrorCode.ERR_601);
        }

        JSONObject obj= StringUtils.instance.getBaseResultObj();
        obj.put("openid",openid);
        obj.put("base",getEntity(openid));
        return obj;
    }

    private TUser getEntity(String openid){
        TUser ent=(TUser) redisUtil.get(RedisKeys.userInfo.getVal(openid));
        if(ent==null) {
            QueryWrapper<TUser> qw = new QueryWrapper<>();
            qw.eq("openid", openid);
            qw.last("limit 1");
            ent=getOne(qw);
            if(ent==null){
                ent=new TUser();
                ent.setOpenid(openid);
                save(ent);
            }
            redisUtil.set(RedisKeys.userInfo.getVal(openid),ent);
        }
        return ent;
    }

    //获取微信手机号
    private String getWxPhone(HttpServletRequest request,String code){
        String url="https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token="+getAccessToken();
        Map<String, Object> map = new HashMap<>(1);
        map.put("code",code);
        String res = HttpUtils.instance.doPostParams(url, map);
        JSONObject jsonObject = JSON.parseObject(res);
        if(jsonObject.getIntValue("errcode")==0){
            return jsonObject.getJSONObject("phone_info").getString("phoneNumber");
        }
        return "";
    }

    //删除缓存
    public void cleanRedis(String openid){
        redisUtil.del(RedisKeys.userInfo.getVal(openid));
        try {
            Thread.sleep(200);
            redisUtil.del(RedisKeys.userInfo.getVal(openid));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
